package com.xbongbong.paas.script.distributor.impl;

import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.vo.StatementAddVO;
import com.xbongbong.paas.script.distributor.StatementCreate;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.pro.customerstatement.pojo.StatementCustomerPojo;
import com.xbongbong.pro.customerstatement.pojo.dto.StatementCondition;
import com.xbongbong.pro.customerstatement.pojo.dto.batch.StatementBatchAddDTO;
import com.xbongbong.pro.enums.fund.enums.FundSetMenuEnum;
import com.xbongbong.pro.enums.fund.enums.PeriodTypeEnum;
import com.xbongbong.pro.fundset.pojo.FundSetPeriodFilterPojo;
import com.xbongbong.pro.fundset.pojo.FundSetPeriodRulePojo;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.FundSetEntity;
import com.xbongbong.saas.help.FundHelp;
import com.xbongbong.saas.model.FundSetModel;
import com.xbongbong.saas.service.CustomerStatementStatisticService;
import com.xbongbong.sys.help.SysEnvHelp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author zcp
 * @version v1.0
 * @since v1.0
 */
@Service("StatementCreate")
public class StatementCreateImpl implements StatementCreate {
    private static final Logger LOG = LoggerFactory.getLogger(StatementCreateImpl.class);
    @Resource
    private FundSetModel fundSetModel;
    @Resource
    private CustomerStatementStatisticService customerStatementStatisticService;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private SysEnvHelp sysEnvHelp;

    @Override
    @Async(value = "createStatementThreadPool")
    public StatementAddVO autoCreate() {
        boolean isGrayEnvironmentEnable = sysEnvHelp.isGrayEnvironmentEnable();
        // 1.获取对账单规则表，只处理当天
        Map<String, Object> param = new HashMap<>(16);
        param.put("refType", FundSetMenuEnum.RECONCILIATION_RULE.getRefType());
        param.put("type", FundSetMenuEnum.RECONCILIATION_RULE.getType());
        param.put("enable", 1);
        param.put("del", DelEnum.NORMAL.getDel());
        Integer start = 0;
        //每次查询200条
        Integer pageNum = 1000;
        Long idGte = 0L;
        param.put("start", start);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        while (true) {
            param.put("idGte", idGte);
            List<FundSetEntity> fundSetEntityList = fundSetModel.findEntitys(param);
            if (fundSetEntityList == null || fundSetEntityList.size() == 0) {
                break;
            }
            idGte = fundSetEntityList.get(fundSetEntityList.size() - 1).getId();
            List<StatementBatchAddDTO> batchAddList = new ArrayList<>();
            for (FundSetEntity fundSetEntity : fundSetEntityList) {
                String corpid = fundSetEntity.getCorpid();

                if (sysEnvHelp.isGrayEnvironment()) {
                    if (!isGrayEnvironmentEnable) {
                        continue;
                    }
                    if (!sysEnvHelp.checkIsCrayCompany(corpid)) {
                        continue;
                    }
                } else {
                    if (isGrayEnvironmentEnable) {
                        if (sysEnvHelp.checkIsCrayCompany(corpid)) {
                            continue;
                        }
                    }
                }

                List<FundSetPeriodFilterPojo> periodFilter = JsonHelperUtil.parseArray(fundSetEntity.getPeriodFilter(), FundSetPeriodFilterPojo.class);
                if (CollectionsUtil.isEmpty(periodFilter)) {
                    continue;
                }
                StatementBatchAddDTO statementBatchAddDTO = getInsertStatementList(corpid, periodFilter);
                if (CollectionsUtil.isNotEmpty(statementBatchAddDTO.getConditionList())) {
                    batchAddList.add(statementBatchAddDTO);
                }
            }
            // 2.批量处理公司的对账单生成
            if (CollectionsUtil.isNotEmpty(batchAddList)) {
                customerStatementStatisticService.createStatement(batchAddList);
            }
        }
        return new StatementAddVO();
    }


    /**
     * 根据公司的自动对账规则获取需要生成对账的客户与对账日期
     * @param corpid
     * @param periodFilter
     * @return
     * @author 石安
     * @since v1.0
     * @version v1.0
     * @update by zcp 从AutoStatementScriptController移入
     */
    private StatementBatchAddDTO getInsertStatementList(String corpid, List<FundSetPeriodFilterPojo> periodFilter) {
        StatementBatchAddDTO statementBatchAddDTO = new StatementBatchAddDTO();
        List<StatementCondition> conditionList = new ArrayList<>();
        statementBatchAddDTO.setCorpid(corpid);
        long now = DateTimeUtil.getInt();
        for (FundSetPeriodFilterPojo filterPojo : periodFilter) {
            if (CollectionsUtil.isEmpty(filterPojo.getRule())) {
                continue;
            }
            FundSetPeriodRulePojo rule = filterPojo.getRule().get(0);
            // 只处理起止日期为上周，上月，去年的
            if (!Objects.equals(StringConstant.LAST, rule.getPrefix())) {
                continue;
            }
            PeriodTypeEnum periodTypeEnum = PeriodTypeEnum.getByCode(rule.getType());
            List<Long> checkingDate = new ArrayList<>();
            switch (periodTypeEnum) {
                case WEEK:
                    // 按周生成
                    if (Objects.equals(rule.getDay(), DateTimeUtil.getWeekInSomeday4Normal(now))) {
                        // 当前时间的一周前时间点
                        checkingDate.add(now - TimeConstant.SECONDS_PER_WEEK);
                        checkingDate.add(now - 1);
                    }
                    break;
                case MONTH:
                    // 按月生成
                    if (Objects.equals(rule.getDay(), DateTimeUtil.getTodayNumInMonth())) {
                        // 当前时间的一个月前时间点
                        int monthDay = DateTimeUtil.getDaysOfMonth(new Date(now * 1000));
                        checkingDate.add(now - monthDay * TimeConstant.SECONDS_PER_DAY);
                        checkingDate.add(now - 1);
                    }
                    break;
                case YEAR:
                    // 按年生成
                    if (Objects.equals(rule.getDay(), DateTimeUtil.getTodayNumInMonth()) && Objects.equals(rule.getMonth(), DateTimeUtil.getMonth4Someday(now))) {
                        // 当前时间的一年前的时间点
                        int year = DateTimeUtil.getCurrentYearDays(new Date(now * 1000));
                        checkingDate.add(now - year * TimeConstant.SECONDS_PER_DAY);
                        checkingDate.add(now - 1);
                    }
                    break;
                default:
                    break;
            }
            if (CollectionsUtil.isEmpty(checkingDate)) {
                continue;
            }
            // 获取有对账流水的客户
            Set<Long> customerIdSet = new HashSet<>();
            try {
                StatementCustomerPojo statementCustomerPojo = fundHelp.getStatementCustomerPojo(checkingDate);
                customerIdSet = fundHelp.getStatementCustomerIdList(null, corpid, statementCustomerPojo);
            } catch (XbbException exception) {
                LOG.error(exception.getMsg());
            }
            for (Long customerId : customerIdSet) {
                StatementCondition condition = new StatementCondition();
                condition.setCustomerId(customerId);
                condition.setCheckingDate(checkingDate);
                conditionList.add(condition);
            }
        }
        statementBatchAddDTO.setConditionList(conditionList);
        return statementBatchAddDTO;
    }
}
